﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tab2Sql.Classes
{
    /// <summary>
    /// New Attempt as of 05/11/2009 21:09:25
    /// </summary>
    public class Options
    {
		/// <summary>
		/// Default and only constructor. 
		/// </summary>
        public Options()
        {
            tableName = "#foo";
            delimiter = "\t";
            addColumnsAddRequired = true;
            addColumnsAddRequired = true;
            maximumColumns = 1000;
            maximumRows = 10000000;
            autoDetectDelimiter = true;
            batchSize = 500;
            addColumnsAddRequired = true;
            firstRowIsHeader = true;
            SqlVariant = SqlVariants.TSql;
            statementType = SqlStatementType.Standard;
            useColumnHeadings = ColumnHeadings.None;
            columnNameModel = HandlingOfColumnNames.Standard;
            autoDetectDelimiterRowLimit = 500;
            outputType = OutputTypes.Default;
            multiInsertThreshold = 1000;
            try
            {
                statementType = SqlStatementType.Standard;
                TableName = Properties.Settings.Default.TableName;
                batchSize = Properties.Settings.Default.BatchSize;
                delimiter = Properties.Settings.Default.Delimiter;
                includeQueryFooter = Properties.Settings.Default.IncludeQueryFooter;
                sqlVariant = GetSqlVariant(Properties.Settings.Default.SqlVariant);
                useColumnHeadings = ColumnHeadings.None;
                autoDetectDelimiterRowLimit = Properties.Settings.Default.AutoDetectDelimiterRowLimit;
                multiInsertThreshold = Properties.Settings.Default.MultiInsertLimit;

               
            }
            catch
            {
                tableName = "#foo";
                delimiter = "\t";
                maximumColumns = -1;
                maximumRows = -1;
                SqlVariant = SqlVariants.TSql;
                statementType = SqlStatementType.Standard;
                useColumnHeadings = ColumnHeadings.None;
                
            }

        }
		/// <summary>
		/// Converts user supplied sqlvariant into SqlVariants enum type. This is used by the settings form so user
		/// can enter the desired sql variant (e.g. tsql / ansi / informix) and Tab2Sql knows what that means. 
		/// Very little error checking is done, so user input should be precise - e.g. t-sql/t.sql/transactsql will NOT work.
		/// All input is converted to lower case so function is not case sensitive.
		/// If supplied variant does not exist/match then function returns SqlVariant.TSql by default.
		/// </summary>
		/// <param name="p">
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>
		/// A <see cref="SqlVariants"/>
		/// </returns>
        public SqlVariants GetSqlVariant(string p)
        {
            string q = p.ToLower().Trim();
            q = q.Replace(" ",String.Empty);
            switch (q)
            {
                case "tsql":
                    return SqlVariants.TSql;
                case "sqlanywhere":
                    return SqlVariants.SqlAnywhere;
                case "ansi":
                    return SqlVariants.ANSI;
                case "informix":
                    return SqlVariants.Informix;
                case "msaccess":
                    return SqlVariants.MSAccess;
                case "sqlite":
                    return SqlVariants.Sqlite;
                default:
                    return SqlVariants.TSql;
            }
        }
        /// <summary>
        /// How much should we 'fix' columnName headings to make them sql safe?
        /// </summary>
        private HandlingOfColumnNames columnNameModel;
        /// <summary>
        ///
        /// </summary>
        public HandlingOfColumnNames ColumnNameModel
        {
            get { return columnNameModel; }
            set { columnNameModel = value; }
        }

        private bool firstRowIsHeader;
        /// <summary>
        /// Simple enough. Default behaviour assumes your data has a header row. If not, this should be false.
        /// When false, the Columns are labelled C0,C1,C2,etc.
        /// </summary>
        public bool FirstRowIsHeader
        {
            get { return firstRowIsHeader; }
            set { firstRowIsHeader = value; }
        }


        private bool autoDetectDelimiter;
        /// <summary>
        /// Should we guess the delimiter? Default=yes.
        /// </summary>
        public bool AutoDetectDelimiter
        {
            get { return autoDetectDelimiter; }
            set { autoDetectDelimiter = value; }
        }

        private int autoDetectDelimiterRowLimit;
        /// <summary>
        /// How many rows should we check/sample when detecting delimiter.
        /// </summary>
        public int AutoDetectDelimiterRowLimit
        {
            get { return autoDetectDelimiterRowLimit; }

        }


        private OutputTypes outputType;
        /// <summary>
        /// 
        /// </summary>
        public OutputTypes OutputType
        {
            get { return outputType; }
            set { outputType = value; }
        }

        /// <summary>
        /// Should columnName headings be specified in INSERT statements.
        /// </summary>
        private ColumnHeadings useColumnHeadings;
        /// <summary>
        /// Should columnName headings be specified in INSERT statements.
        /// </summary>
        public ColumnHeadings UseColumnHeadings
        {
            get { return useColumnHeadings; }
            set { useColumnHeadings = value; }
        } 


        private string tableName;
        /// <summary>
        /// Desired target table name. Usually foo or equivalent is default. BE CAREFUL NOT TO RE-USE EXISTING TABLES.
        /// </summary>
        public string TableName
        {
            get { return tableName; }
            set { tableName = value; }
        }
        /// <summary>
        ///
        /// </summary>
        public string[] DelimiterAsArray2
        {
            get
            {
                string[] x = new string[1];
                x[0] = Delimiter;
                return x;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <returns>
        /// A <see cref="System.String[]"/>
        /// </returns>
        public string[] DelimiterAsArray()
        {
            string[] x = new string[1];
            x[0] = Delimiter;
            return x;
        }

        private string delimiter;
		/// <summary>
		/// Column / field delimiter - NOT row/line delimiter. 
		/// </summary>
        public string Delimiter
        {
            get
            {

                string[] x = new string[1];

                x[0] = delimiter;
                if (x[0] == "\\t")
                { x[0] = "\t"; }
                if (x[0] == @"\\|")
                { x[0] = @"\|"; }
                if (x[0] == @"|")
                { x[0] = @"\|"; }
                string endResult = string.Empty;
                endResult = x[0];
                if (endResult.Length == 0 || endResult == null || endResult.Trim().Length == 0)
                {
                    endResult = "\t";
                }

                return endResult;
            }

            set
            {
                if (value.Trim().Length > 0 && value != " " || value == "\t")
                {
                    if (value == "\\t")
                    {
                        delimiter = "\t";
                    }
                    else if
                        (value == @"\,")
                    {
                        delimiter = ",";
                    }
                    else if (value == @"\|") { delimiter = "|"; }
                    else
                    {
                        delimiter = value;
                    }
                }
                
            }
        }
        

        private int maximumRows;
        /// <summary>
        /// Upper limit on rows. Sensible values will depend on width of data. On basic datatables with less than 10
        /// columns you should be able to process 100k rows with no problem. I've tested up to 500-600k rows and it did
        /// finish but performance/memory usage were horrific.
        /// </summary>
        public int MaximumRows
        {
            get { return maximumRows; }
            set { maximumRows = value; }
        }
        private int maximumColumns;
        /// <summary>
        /// Max number of columns. If set too high then you may experience crashing if Tab2Sql misdetects your delimiter.
        /// 3000 is the upper limit for sensible usage. (Performance will still be terrible on the SQL end though.
        /// </summary>
        public int MaximumColumns
        {
            get { return maximumColumns; }
            set { maximumColumns = value; }
        }
        

        #region output options

        private SqlVariants sqlVariant;
        /// <summary>
        /// What is the target SQL platform? SQL Server/SQL Anywhere/Sqlite/MySql/etc...
        /// </summary>
        public SqlVariants SqlVariant
        {
            get { return sqlVariant; }
            set { sqlVariant = value; }
        }

        private SqlStatementType statementType;
        /// <summary>
        /// Is this a Standard statement (i.e. create table then insert) or not.
        /// Other behaviours not really supported consistently.
        /// </summary>
        public SqlStatementType StatementType
        {
            get { return statementType; }
            set { statementType = value; }
        }

        private int batchSize;
        /// <summary>
        /// Number of rows per batch in multi statement mode. Larger number=bigger transactions, therefore performance
        /// will depend heavily on chosen value. Some SQL engines/clients perform terribly with very large transactions,
        /// others choke if there's too many small transactions.
        /// </summary>
        public int BatchSize
        {
            get { return batchSize; }
            set { batchSize = value; }
        }

        private int multiInsertThreshold;
        /// <summary>
        /// Above this number, regardless of what is selected in the GUI, multi-statment SQL is generated.
        /// set to a very high value to disable this behaviour.
        /// </summary>
        public int MultiInsertThreshold
        {
            get { return multiInsertThreshold; }
            set { multiInsertThreshold = value; }
        }

        private bool skipLineComments;
        /// <summary>
        /// Skip input lines which start with #?
        /// </summary>
        public bool SkipLineComments {
            get {
                return this.skipLineComments;
            }
            set {
                skipLineComments = value;
            }
        }

        private RowID includeRowNumber;
        /// <summary>
        ///
        /// </summary>
        public RowID IncludeRowNumber
        {
            get { return includeRowNumber; }
            set { includeRowNumber = value; }
        }

        private bool includeQueryFooter;
        /// <summary>
        ///
        /// </summary>
        public bool IncludeQueryFooter
        {
            get { return includeQueryFooter; }
            set { includeQueryFooter = value; }
        }

        #endregion

        private bool addColumnsAddRequired;
        /// <summary>
        ///
        /// </summary>
        public bool AddColumnsAddRequired
        {
            get { return addColumnsAddRequired; }
            set { addColumnsAddRequired = value; }
        }




    }
}
